using System;
using System.Collections.Generic;
using System.Text;
using FlatRedBall;
using FlatRedBall.Input;
using FlatRedBall.AI.Pathfinding;
using FlatRedBall.Graphics.Animation;
using FlatRedBall.Graphics.Particle;

using FlatRedBall.Graphics.Model;
using FlatRedBall.Math.Geometry;
using FlatRedBall.Math.Splines;

using Cursor = FlatRedBall.Gui.Cursor;
using GuiManager = FlatRedBall.Gui.GuiManager;
using FlatRedBall.Localization;

#if FRB_XNA || SILVERLIGHT
using Keys = Microsoft.Xna.Framework.Input.Keys;
using Vector3 = Microsoft.Xna.Framework.Vector3;
using Texture2D = Microsoft.Xna.Framework.Graphics.Texture2D;
#endif

using NereusGame.Entities.Ships.Enemies;
using NereusGame.Entities.Ships;
using NereusGame.Entities.HBodies;
using NereusGame.Entities.Projectiles;
using FlatRedBall.Instructions;

namespace NereusGame.Screens
{
    public partial class SolarSystem
    {
        private bool bossAlive;
        private const float PLAYER_DENSITY = 1f;
        private const float ASTEROID_DENSITY = 4f;
        private const float ENEMY_DENSITY = 1.5f;

        protected const float g = .001f;
        protected const string CONTEN_MANAGER = "NereusGameContent";   // Name of the contentManager



       // protected Xbox360GamePad gamePad;
        protected List<Player> Players;                                     // List of players
        protected List<Star> Stars;                                         // List of Stars
        protected List<Asteroid> Asteroids;                                 // List of Asteroids
        protected List<Planet> Planets;                                     // List of Planets
        protected List<Enemy> Enemies;                                      // List of Enemies
        protected List<Projectile> ActiveProjectiles;
        protected List<Projectile> InactiveProjectiles;

        Emitter collisionEmitter;

        protected Sprite backGround;  // background for the level

        void CustomInitialize()
        {
            bossAlive = false;

            InitializeBackGround();
            InitializeCollisionEmitter();
            InitializeController1();
            InitializeController2();
       
        }

        void CustomActivity(bool firstTimeCalled)
        {
            
            // pause game when engine is paused
            if (!InstructionManager.IsEnginePaused)
            {
                if (Enemies.Count <= 5 && !bossAlive && Game1.mGameMode != Game1.GameMode.Arena)
                {
                    for (int i = Enemies.Count - 1; i > 0; i--)
                    {
                        if (Enemies[i].IsBoss)
                        {
                            Enemies[i].Position = Players[0].Position;
                            Enemies[i].Position.X += 20f;
                            Enemies[i].Position.Y -= 10f;
                            Enemies[i].setAngryState();
                            bossAlive = true;
                            break;
                        }
                    }
                }
                WorldActivity();
                DetectWorldCollision();
                arenamodecollision();   /// needs to change

                CheckForDeadUnits();
            }
                for(int i = 0; i < Players.Count; i++)
                    Players[i].pauseMenu.Update();
       
          


        }

        void CustomDestroy()
        {
            SpriteManager.RemoveSprite(backGround);     // remove the background sprite

            // remove all player sprites
            for (int i = 0; i < Players.Count; i++)
                Players[i].Destroy();

            // remove all enemy sprites
            for (int i = 0; i < Enemies.Count; i++)
                Enemies[i].Destroy();

            // remove all planet sprites
            if (Planets != null)
            {
                for (int i = 0; i < Planets.Count; i++)
                    Planets[i].Destroy();
            }

            // remove al asteroids sprites
            for (int i = 0; i < Asteroids.Count; i++)
                Asteroids[i].Destroy();
            // remove all star sprites
            for (int i = 0; i < Stars.Count; i++)
                Stars[i].Destroy();

            ActiveProjectiles.Clear();

            InactiveProjectiles.Clear();

            base.Destroy();

        }

        static void CustomLoadStaticContent(string contentManagerName)
        {


        }

        private void InitializeCollisionEmitter()
        {
            collisionEmitter = new Emitter();
            collisionEmitter.Texture = CollisionDust;
            collisionEmitter.EmissionSettings.RadialVelocity = 10f;
            collisionEmitter.EmissionSettings.RadialVelocityRange = 10f;

            collisionEmitter.EmissionSettings.Drag = .5f;
            collisionEmitter.RemovalEvent = Emitter.RemovalEventType.Alpha0;
            collisionEmitter.NumberPerEmission = 20;
            collisionEmitter.EmissionSettings.ScaleX = .5f;
            collisionEmitter.EmissionSettings.ScaleY = .5f;
            collisionEmitter.EmissionSettings.AlphaRate = -1f;
            collisionEmitter.EmissionSettings.ZVelocityRange = 20f;
            collisionEmitter.EmissionSettings.RotationXVelocityRange = 314f;
            collisionEmitter.EmissionSettings.RotationYVelocityRange = 314f;
        }

        // Initialize the level's background
        private void InitializeBackGround()
        {
            backGround = new Sprite();
            SpriteManager.AddSprite(backGround);
            /*
            backGround.ScaleX = 150;
            backGround.ScaleY = 60f;
            backGround.Z = -1;
             */
        }

       

        protected void InitializeController1()
        {

            // InputManager.Xbox360GamePads[0]; // assign gamepad

        }


        protected void InitializeController2()
        {

            if (FlatRedBall.Input.InputManager.Xbox360GamePads[1].IsConnected == false)
            {
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap = new KeyboardButtonMap();
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap.RightAnalogDown = Keys.K;
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap.RightAnalogUp = Keys.I;
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap.RightAnalogLeft = Keys.J;
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap.RightAnalogRight = Keys.L;
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap.LeftAnalogDown = Keys.Down;
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap.LeftAnalogUp = Keys.Up;
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap.LeftAnalogLeft = Keys.Left;
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap.LeftAnalogRight = Keys.Right;
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap.Back = Keys.Z;
                FlatRedBall.Input.InputManager.Xbox360GamePads[1].ButtonMap.Start = Keys.X;
            }

        }
        //*****************************************************Activity*****************************************************************//

        // Allows for World Activity
        private void WorldActivity()
        { 
            PlayersActivity();
            AsteroidsActivity();
            PlanetsActivity();
            StarsActivity();
            EnemyActivity();
            AliveProjectileActivity();
            DeadProjectileActivity();

        }

        // Calls each Player's activity
        private void PlayersActivity()
        {
            if (Players != null)
            {
                for (int i = 0; i < Players.Count; i++)
                    Players[i].Activity();
            }
        }

        // Calls each Asteroid's activity
        private void AsteroidsActivity()
        {
            if (Asteroids != null)
            {
                for (int i = 0; i < Asteroids.Count; i++)
                    Asteroids[i].Activity();
            }
        }

        // Calls each Planet's Activity
        private void PlanetsActivity()
        {
            if (Planets != null)
            {
                for (int i = 0; i < Planets.Count; i++)
                    Planets[i].Activity();
            }
        }

        // Calls each Star's Activity
        private void StarsActivity()
        {
            if (Stars != null)
            {
                for (int i = 0; i < Stars.Count; i++)
                    Stars[i].Activity();
            }
        }

        // Calls each Enemey's Activity
        private void EnemyActivity()
        {
            if (Enemies != null)
            {
                for (int i = 0; i < Enemies.Count; i++)
                    Enemies[i].Activity();
            }
        }

        private void AliveProjectileActivity()
        {
            for (int i = 0; i < ActiveProjectiles.Count; i++)
            {
                if (!ActiveProjectiles[i].IsAlive())
                {
                    InactiveProjectiles.Add(ActiveProjectiles[i]);
                    ActiveProjectiles.RemoveAt(i);
                    continue;
                }
                ActiveProjectiles[i].Activity();
                ActiveProjectiles[i].Gravitate(Stars, Planets, g);
            }


        }

        private void DeadProjectileActivity()
        {
            for (int i = 0; i < InactiveProjectiles.Count; i++)
            {
                if (InactiveProjectiles[i].IsAlive())
                {
                    ActiveProjectiles.Add(InactiveProjectiles[i]);
                    InactiveProjectiles.RemoveAt(i);
                    continue;
                }
                InactiveProjectiles[i].Activity();
            }

        }


        // for now worrying about only asterids and enemy and players..
        private void DetectWorldCollision()
        {

            PlayerCollisions();
            EnemyCollisions();
            CheckProjectileCollisions();
            AsteroidCollisions();

        }

        private void PlayerCollisions()
        {
            for (int i = 0; i < Players.Count; i++)
            {
                // player VS player
                for (int j = i + 1; j < Players.Count; j++)
                {
                    if (Players[i].Body.CollideAgainstBounce(Players[j].Body, Players[i].Body.Radius * PLAYER_DENSITY, Players[j].Body.Radius * PLAYER_DENSITY, 0.2f))
                    {
                        float damage = (Math.Abs(Players[i].Acceleration.X) + Math.Abs(Players[i].Acceleration.Y)) * 0.5f;
                        Players[i].CurrentHealth -= damage;
                        Players[j].CurrentHealth -= damage;
                        Players[i].hud.Update();
                        Players[j].hud.Update();
                    }
                }

                // player VS asteroid
                for (int j = 0; j < Asteroids.Count; j++)
                {
                    if (Players[i].Body.CollideAgainstBounce(Asteroids[j].Body, Players[i].Body.Radius * PLAYER_DENSITY, Asteroids[j].Body.Radius * ASTEROID_DENSITY, 0.2f)) 
                    {
                        Players[i].CurrentHealth -= (Math.Abs(Players[i].Acceleration.X) + Math.Abs(Players[i].Acceleration.Y)) * 0.5f ;
                        Players[i].hud.Update();
                    }
                }

                // player VS enemy

                for (int j = 0; j < Enemies.Count; j++)
                {
                    if (Players[i].Body.CollideAgainstBounce(Enemies[j].Body, Players[i].Body.Radius * PLAYER_DENSITY, Enemies[j].Body.Radius * ENEMY_DENSITY, 0.2f))
                    {
                        float damage = (Math.Abs(Players[i].Acceleration.X) + Math.Abs(Players[i].Acceleration.Y)) * 0.1f;
                        Players[i].CurrentHealth -= damage;
                        Players[i].hud.Update();
                        Enemies[j].CurrentHealth -= damage;
                        
                        // check for nuetral miner
                        if (!Enemies[j].IsNeutralMiner || !Enemies[j].IsBoss)
                        Enemies[j].setAngryState();
                    }


                }

                // player vs stars
                for (int j = 0; j < Stars.Count; j++)
                {
                    if(Players[i].Body.CollideAgainst(Stars[j].Body))
                    {
                        Players[i].CurrentHealth = 0;
                        Players[i].hud.Update();
                    }
                }

                // players vs planets
                for (int j = 0; j < Planets.Count; j++)
                {
                    if (Players[i].Body.CollideAgainstBounce(Planets[j].Body, Players[i].Body.Radius * PLAYER_DENSITY, Planets[j].Body.Radius * PLAYER_DENSITY, 0.2f))
                    {
                        Players[i].CurrentHealth -= (Math.Abs(Players[i].Acceleration.X) + Math.Abs(Players[i].Acceleration.Y)) * 0.5f;
                        Players[i].hud.Update();
                    }
                }
            }
        }
        private void EnemyCollisions()
        {

            for (int i = 0; i < Enemies.Count; i++)
            {
                // enemy VS enemy
                for (int j = i + 1; j < Enemies.Count; j++)
                {
                    if(Enemies[i].Body.CollideAgainstBounce(Enemies[j].Body, Enemies[i].Body.Radius * PLAYER_DENSITY, Enemies[j].Body.Radius * PLAYER_DENSITY, 0.2f))
                        Enemies[i].CurrentHealth -= (Math.Abs(Enemies[i].Acceleration.X) + Math.Abs(Enemies[i].Acceleration.Y)) * 0.1f;
                }

                // enemy VS asteroid
                for (int j = 0; j < Asteroids.Count; j++)
                {
                    if(Enemies[i].Body.CollideAgainstBounce(Asteroids[j].Body, Enemies[i].Body.Radius * PLAYER_DENSITY, Asteroids[j].Body.Radius * ASTEROID_DENSITY, 0.2f))
                         Enemies[i].CurrentHealth -= (Math.Abs(Enemies[i].Acceleration.X) + Math.Abs(Enemies[i].Acceleration.Y)) * 0.3f;
                }

                // enemy vs stars
                for (int j = 0; j < Stars.Count; j++)
                {
                    if (Enemies[i].Body.CollideAgainst(Stars[j].Body))
                    {
                        Enemies[i].CurrentHealth = 0;
                    }
                }

                // enemy vs planets
                for (int j = 0; j < Planets.Count; j++)
                {
                    if (Enemies[i].Body.CollideAgainstBounce(Planets[j].Body, Enemies[i].Body.Radius * PLAYER_DENSITY, Planets[j].Body.Radius * PLAYER_DENSITY, 0.2f))
                    {
                        Enemies[i].CurrentHealth -= (Math.Abs(Enemies[i].Acceleration.X) + Math.Abs(Enemies[i].Acceleration.Y)) * 0.5f;
                    }
                }
                
            }
        }

        private void AsteroidCollisions()
        {
            for (int i = 0; i < Asteroids.Count; i++)
            {
                // Asteroids VS Asteroids
                for (int j = i + 1; j < Asteroids.Count; j++)
                    if (Asteroids[i].Body.CollideAgainstBounce(Asteroids[j].Body, Asteroids[i].Body.Radius * PLAYER_DENSITY, Asteroids[j].Body.Radius * PLAYER_DENSITY, 0.2f))
                    {
                        collisionEmitter.Position = Asteroids[i].Position - (.5f * Asteroids[j].Position);
                        //collisionEmitter.Emit();
                    }


                // Asteroids vs planets
                for (int j = 0; j < Planets.Count; j++)
                {
                    if (Asteroids[i].Body.CollideAgainstBounce(Planets[j].Body, Asteroids[i].Body.Radius * PLAYER_DENSITY, Planets[j].Body.Radius * PLAYER_DENSITY, 0.2f))
                    {
                        Asteroids[i].CurrentHealth -= (Math.Abs(Asteroids[i].Acceleration.X) + Math.Abs(Asteroids[i].Acceleration.Y)) * 0.2f;
                    }
                }
            }
        }

        private void CheckProjectileCollisions()
        {
            bool isProjectileCollided = false;
            for (int i = 0; i < ActiveProjectiles.Count; i++)
            {
                // collision against players
                for (int j = 0; j < Players.Count; j++)
                {

                        if (ActiveProjectiles[i].Body.CollideAgainst(Players[j].Body))
                        {
                            if (ActiveProjectiles[i].Shooter.GetType().BaseType != Players[j].GetType().BaseType)
                            {
                                Players[j].CurrentHealth -= ActiveProjectiles[i].Damage;
                                Players[j].hud.Update();
                                ActiveProjectiles[i].DeadState();
                                isProjectileCollided = true;
                                break;
                            }
                        }
                    
                }

                // collision against stars
                if (!isProjectileCollided)
                {
                    for (int j = 0; j < Stars.Count; j++)
                    {
                        if (ActiveProjectiles[i].Body.CollideAgainst(Stars[j].Body))
                        {
                            ActiveProjectiles[i].DeadState();

                        }

                    }
                }

                // collision against Asteroids
                if (!isProjectileCollided)
                {
                    for (int j = 0; j < Asteroids.Count; j++)
                    {
                        if (ActiveProjectiles[i].Body.CollideAgainst(Asteroids[j].Body))
                        {
                            Asteroids[j].CurrentHealth -= ActiveProjectiles[i].Damage;
                            ActiveProjectiles[i].DeadState();
                            isProjectileCollided = true;
                            break;
                        }

                    }
                }


                // collision against enemies
                if (!isProjectileCollided)
                {
                    for (int j = 0; j < Enemies.Count; j++)
                    {
                        if (ActiveProjectiles[i].Body.CollideAgainst(Enemies[j].Body))
                        {
                            if (ActiveProjectiles[i].Shooter.GetType().BaseType == Players[0].GetType().BaseType)
                            {
                                
                                Enemies[j].CurrentHealth -= ActiveProjectiles[i].Damage;
                                // check for nuetral miner
                                if (!Enemies[j].IsNeutralMiner || !Enemies[j].IsBoss)
                                    Enemies[j].setAngryState();
                               
                                ActiveProjectiles[i].DeadState();
                                isProjectileCollided = true;
                                break;
                            }
                        }

                    }
                }


                // planet vs projectile
                if (!isProjectileCollided)
                {
                    for (int j = 0; j < Planets.Count; j++)
                    {

                        if (ActiveProjectiles[i].Body.CollideAgainst(Planets[j].Body))
                        {
                            ActiveProjectiles[i].DeadState();
                            isProjectileCollided = true;
                            break;
                        }

                    }
                }



            }

 
        }


        private void arenamodecollision()
        {
            if (Game1.mGameMode == Game1.GameMode.Arena)
            {
                for (int i = 0; i < Players[0].weaponInventory[Players[0].weaponSelector].aliveAmmo.Count; i++)
                {
                    if (Players[0].weaponInventory[Players[0].weaponSelector].aliveAmmo.Peek().Body.CollideAgainst(Players[1].Body))
                    {
                        Players[1].CurrentHealth -= Players[0].weaponInventory[Players[0].weaponSelector].aliveAmmo.Peek().Damage;
                        Players[0].weaponInventory[Players[0].weaponSelector].aliveAmmo.Peek().DeadState();
                        Players[1].hud.Update();


                    }
                    Players[0].weaponInventory[Players[0].weaponSelector].aliveAmmo.Enqueue(Players[0].weaponInventory[Players[0].weaponSelector].aliveAmmo.Dequeue());
                }



                for (int i = 0; i < Players[1].weaponInventory[Players[1].weaponSelector].aliveAmmo.Count; i++)
                {
                    if (Players[1].weaponInventory[Players[1].weaponSelector].aliveAmmo.Peek().Body.CollideAgainst(Players[0].Body))
                    {
                        Players[0].CurrentHealth -= Players[1].weaponInventory[Players[1].weaponSelector].aliveAmmo.Peek().Damage;
                        Players[1].weaponInventory[Players[1].weaponSelector].aliveAmmo.Peek().DeadState();
                        Players[0].hud.Update();

                    }
                    Players[1].weaponInventory[Players[1].weaponSelector].aliveAmmo.Enqueue(Players[1].weaponInventory[Players[1].weaponSelector].aliveAmmo.Dequeue());
                }
   
            }

        }
        private void CheckForDeadUnits()
        {

            // check for dead enemies
            for (int i = 0; i < Enemies.Count; i++)
            {
                if (!Enemies[i].IsAlive())
                {
                    Players[0].increaseScore(Enemies[i].getPoints());
                    Enemies[i].Destroy();
                    Enemies.Remove(Enemies[i]);
                }
            }


            // check for Dead asteroids
            for (int i = 0; i < Asteroids.Count; i++)
            {
                if (!Asteroids[i].IsAlive())
                {
                    Asteroids[i].Destroy();
                    Asteroids.Remove(Asteroids[i]);
                }

            }

        }


        

           
                
    }
}
